﻿@inject IActionService _actionService
@inject IModelCatalogService _modelCatalogService
@inject ChatState _chatState
@implements IDisposable

<MudIconButton DisableElevation="false" Icon="@Icons.Material.Filled.AutoAwesome" OnClick="@ToggleOpen" id="prompt-input-plugins-button" Color="Color.Inherit">
</MudIconButton>
<MudPopover Open="_isOpen" OverflowBehavior="OverflowBehavior.FlipAlways" AnchorOrigin="Origin.BottomCenter" TransformOrigin="Origin.TopCenter" Paper="false">
    <ChildContent>
        <MudPaper Outlined="true" Class="mx-2">
            <MudAutocomplete @ref="_autocomplete"
                             Value="CurrentValue"
                             Placeholder="Unleash magic 🧙 – pick an action"
                             T="NativeActionResponse"
                             ToStringFunc="@(item => item?.Name)"
                             Immediate="true"
                             CoerceValue="@coerceValue"
                             CoerceText="@coerceText"
                             SearchFunc="@SearchAsync"
                             Clearable="true"
                             ResetValueOnEmptyText="true"
                             ShowProgressIndicator="true"
                             ProgressIndicatorColor="Color.Primary"
                             CloseIcon="@Icons.Material.Filled.Search"
                             AdornmentColor="Color.Primary"
                             MaxItems="null"
                             AutoFocus="false"
                             Margin="Margin.Dense"
                             DisableUnderLine="true"
                             Style="width: 400px"
                             Class="mx-2"
                             ValueChanged="OnValueChanged"
                             IsOpenChanged="OnAutocompleteMenuChanged">
                <ItemTemplate Context="context">
                    <div class="d-flex flex-row flex-grow-1 gap-3 align-items-center">
                        <MudIcon Class="my-auto" Icon="@context.Icon" Size="@Size.Small" />
                        <MudText Typo="Typo.body1">@context.Name</MudText>
                    </div>
                </ItemTemplate>
                <ItemSelectedTemplate Context="context">
                    <div class="d-flex flex-row flex-grow-1 gap-3 align-items-center">
                        <MudIcon Class="my-auto" Icon="@context.Icon" Size="@Size.Small" />
                        <MudText Typo="Typo.body1">@context.Name</MudText>
                    </div>
                </ItemSelectedTemplate>
            </MudAutocomplete>
        </MudPaper>
    </ChildContent>
</MudPopover>

@code 
{
    [Parameter] public EventCallback<NativeActionResponse> ActionChanged { get; set; }
    [Parameter] public NativeActionResponse? CurrentValue { get; set; }
    [Parameter] public List<NativeActionResponse> Actions { get; set; } = new();

    private MudAutocomplete<NativeActionResponse>? _autocomplete;
    private ModelCatalogResponse ModelCatalog { get; set; } = new();

    private bool coerceText;
    private bool coerceValue;
    private bool _isOpen = false;
    private bool _isAutocompleteOpen = false;

    protected override async Task OnInitializedAsync()
    {
        _chatState.ActionsRefreshed += async () => await LoadActions();
        _chatState.NativeActionServiceChanged += StateHasChanged;

        await LoadActions();
        await LoadModelCatalog();
    }

    private async Task LoadActions()
    {
        var response = await _actionService.BrowseActions();
        var actions = response.Value;

        if (actions is not null)
        {
            Actions = actions.ToList();
        }
    }

    private async Task LoadModelCatalog()
    {
        var response = await _modelCatalogService.BrowseModelsCatalog();
        var modelCatalog = response.Value;

        if (modelCatalog is not null)
        {
            ModelCatalog = modelCatalog;
        }
    }

    private async Task<IEnumerable<NativeActionResponse>> SearchAsync(string value)
    {
        if (string.IsNullOrEmpty(value))
        {
            return Actions;
        }

        var result = Actions
            .Where(x => x.Name.Contains(value, StringComparison.InvariantCultureIgnoreCase));

        return await Task.FromResult(result);
    }

    private async Task ToggleOpen()
    {
        _isOpen = !_isOpen;

        await (_isOpen switch
        {
            true => OpenMenuAsync(),
            false => CloseMenuAsync(),
        });
    }

    private async Task OpenMenuAsync()
    {
        await Task.Delay(50);
        await ToggleMenu();
    }

    private async Task CloseMenuAsync()
    {
        if (_isAutocompleteOpen)
        {
            await ToggleMenu();
        }
    }

    private async Task ToggleMenu()
    {
        if (_autocomplete is not null)
        {
            await _autocomplete.ToggleMenu();
        }
    }

    private void OnAutocompleteMenuChanged(bool isOpen)
    {
        _isAutocompleteOpen = isOpen;

        if (!isOpen && _isOpen)
        {
            _isOpen = false;
        }
    }

    private void OnValueChanged(NativeActionResponse action)
    {
        if (action is not null)
        {
            var serviceId = ModelCatalog.Models.SingleOrDefault(x => x.Name == action.Model)?.Provider ?? string.Empty;
            _chatState.SetNativeActionServiceId(serviceId);

            ActionChanged.InvokeAsync(action);
            _isOpen = false;
        }
    }

    public void Dispose()
    {
        _chatState.ActionsRefreshed -= async () => await LoadActions();
        _chatState.NativeActionServiceChanged -= StateHasChanged;
    }
}
